package kr.ac.kaist.idb.csnql.clause;

import java.io.Serializable;
import java.util.*;



/**
 * 
 * @brief Store one tuple of the query
 * @author Jongheon Park (korex527@kaist.ac.kr)
 *
 */
public class SNQLTuple implements Serializable
{
	
	/**
	 * @brief Serial version UID which is automatically generated
	 */
	private static final long serialVersionUID = -6507994457218485834L;

	/** @brief attribute list */
    private Vector<String> attributes_;
    
    /** @brief value list */
    private Vector<Object> values_;
    
    /** @brief search table of tuple */
    private Hashtable<String, Integer> searchTable_;

    /**
     * @brief Instantiates a new SNQLTuple
     */
    public SNQLTuple()
    {
        attributes_ = new Vector<String>();
        values_ = new Vector<Object>();
        searchTable_ = new Hashtable<String, Integer>();
    }

    /**
     * @brief Instantiates a new SNQLTuple with concatenated string
     *
     * @param s the concatenated string
     */
    public SNQLTuple(String s)
    {
        this();
        for(StringTokenizer stringtokenizer = new StringTokenizer(s, ","); stringtokenizer.hasMoreTokens(); setAtt(stringtokenizer.nextToken().trim(), null));
    }
    
    /**
     * @brief Instantiates a new sNQL tuple with SensingData instance
     *
     * @param data the SensingData instance
     */
    public SNQLTuple(SensingData data)
	{
    	this();
    	
		setAtt("sensorid", data.getSensorID());
		setAtt("timestamp", data.getTimestamp());
		
		for(int i= 0 ; i < data.getAttribute().size(); i++)
		{	
			setAtt((String) data.getAttribute().get(i), data.getValue().get(i));
		}
	}

    /**
     * @param s Concatenated row
     * @brief Set the row
     */
    public void setRow(String s)
    {
        StringTokenizer stringtokenizer = new StringTokenizer(s, ",");
        for(int i = 0; stringtokenizer.hasMoreTokens(); i++)
        {
            String s1 = stringtokenizer.nextToken().trim();
            try
            {
                Double double1 = new Double(s1);
                setAtt(getAttName(i), double1);
            }
            catch(Exception exception)
            {
                setAtt(getAttName(i), s1);
            }
        }

    }

    /**
     * @param vector New row vector list
     * @brief Set the row
     */
    public void setRow(Vector<?> vector)
    {
        for(int i = 0; i < vector.size(); i++)
            setAtt(getAttName(i), vector.elementAt(i));

    }

    /**
     * @brief Set the attribute
     *
     * @param s the attribute name
     * @param obj the value object
     */
    public void setAtt(String s, Object obj)
    {
        if(s != null)
        {
            boolean flag = searchTable_.containsKey(s);
            if(flag)
            {
                int i = ((Integer)searchTable_.get(s)).intValue();
                values_.setElementAt(obj, i);
            } else
            {
                int j = attributes_.size();
                attributes_.addElement(s);
                values_.addElement(obj);
                searchTable_.put(s, new Integer(j));
            }
        }
    }

    /**
     * @brief Get the attribute name
     *
     * @param i The index
     * @return The attribute name
     */
    public String getAttName(int i)
    {
        try
        {
            return (String)attributes_.elementAt(i);
        }
        catch(ArrayIndexOutOfBoundsException arrayindexoutofboundsexception)
        {
            return null;
        }
    }

    /**
     * @param s The attribute name
     * @return The attribute index
     * @brief Get the attribute index
     */
    public int getAttIndex(String s)
    {
        if(s == null)
            return -1;
        Integer integer = (Integer)searchTable_.get(s);
        if(integer != null)
            return integer.intValue();
        else
            return -1;
    }

    /**
     * @param i The index
     * @return The attribute value
     * @brief Get the attribute value by index
     */
    public Object getAttValue(int i)
    {
        try
        {
            return values_.elementAt(i);
        }
        catch(ArrayIndexOutOfBoundsException arrayindexoutofboundsexception)
        {
            return null;
        }
    }

    /**
     * @param s The attribute name
     * @return The attribute value
     * @brief Get the attribute value by attribute name
     */
    public Object getAttValue(String s)
    {
        boolean flag = false;
        if(s != null)
            flag = searchTable_.containsKey(s);
        if(flag)
        {
            int i = ((Integer)searchTable_.get(s)).intValue();
            return values_.elementAt(i);
        } else
        {
            return null;
        }
    }

    /**
     * @param s The attribute name
     * @return true, if there is attribute.
     * @brief Checks if there is attribute.
     */
    public boolean isAttribute(String s)
    {
        if(s != null)
            return searchTable_.containsKey(s);
        else
            return false;
    }

    /**
     * @return the number of attributes
     * @brief Get the number of attributes
     */
    public int getNumAtt()
    {
        return values_.size();
    }

    public String toString()
    {
        StringBuffer stringbuffer = new StringBuffer();
        stringbuffer.append("[");
        if(attributes_.size() > 0)
        {
            Object obj = attributes_.elementAt(0);
            String s;
            if(obj == null)
                s = "(null)";
            else
                s = obj.toString();
            Object obj2 = values_.elementAt(0);
            String s2;
            if(obj2 == null)
                s2 = "(null)";
            else
                s2 = obj2.toString();
            stringbuffer.append(s + " = " + s2);
        }
        for(int i = 1; i < attributes_.size(); i++)
        {
            Object obj1 = attributes_.elementAt(i);
            String s1;
            if(obj1 == null)
                s1 = "(null)";
            else
                s1 = obj1.toString();
            Object obj3 = values_.elementAt(i);
            String s3;
            if(obj3 == null)
                s3 = "(null)";
            else
                s3 = obj3.toString();
            stringbuffer.append(", " + s1 + " = " + s3);
        }

        stringbuffer.append("]");
        return stringbuffer.toString();
    }
}
